from flask import request, jsonify, send_file
import os
import json
import tempfile
import base64
import parselmouth
import numpy as np
from db_config import execute_query
from tone_analyzer import analyze_audio_data, compute_semitones, normalize_time, fit_curve, extract_fit_coefficients

def get_all_characters():
    """
    接口1：查询所有字，返回字、拼音和声调
    
    返回:
        JSON格式的所有汉字数据，包含字、拼音和声调
    """
    try:
        query = """
        SELECT DISTINCT character_text, pinyin, tone_type
        FROM standard_audios
        ORDER BY character_text
        """
        results = execute_query(query)
        
        characters = []
        for row in results:
            characters.append({
                "character": row["character_text"],
                "pinyin": row["pinyin"],
                "tone": row["tone_type"]
            })
        
        return jsonify({
            "status": "success",
            "data": characters,
            "count": len(characters)
        })
    
    except Exception as e:
        return jsonify({
            "status": "error",
            "message": str(e)
        }), 500

def get_characters_by_tone(tone):
    """
    接口2：按声调查询所有字，返回字、拼音和声调
    
    参数:
        tone (int): 声调类型（1-4）
        
    返回:
        JSON格式的指定声调的汉字数据，包含字、拼音和声调
    """
    try:
        if tone < 1 or tone > 4:
            return jsonify({
                "status": "error",
                "message": "声调类型必须在1-4之间"
            }), 400
            
        query = """
        SELECT DISTINCT character_text, pinyin, tone_type
        FROM standard_audios
        WHERE tone_type = %s
        ORDER BY character_text
        """
        results = execute_query(query, (tone,))
        
        characters = []
        for row in results:
            characters.append({
                "character": row["character_text"],
                "pinyin": row["pinyin"],
                "tone": row["tone_type"]
            })
        
        return jsonify({
            "status": "success",
            "data": characters,
            "count": len(characters),
            "tone": tone
        })
    
    except Exception as e:
        return jsonify({
            "status": "error",
            "message": str(e)
        }), 500

def analyze_tone():
    """
    接口3：声调曲线分析
    
    接收:
        - wav格式音频文件（用户录音）
        - 要读的字
        - 拼音
        - 声调
        
    返回:
        - 归一化后的用户录音点集合（时间和半音值）
        - 拟合曲线参数
        - 归一化后的标准音频点集合
        - 标准音频拟合曲线参数
    """
    try:
        # 检查是否有文件上传
        if 'audio' not in request.files:
            return jsonify({
                "status": "error",
                "message": "未找到音频文件"
            }), 400
            
        # 获取请求参数
        audio_file = request.files['audio']
        character = request.form.get('character')
        pinyin = request.form.get('pinyin')
        tone = request.form.get('tone')
        
        # 验证参数
        if not character or not pinyin or not tone:
            return jsonify({
                "status": "error",
                "message": "缺少必要参数：character, pinyin, tone"
            }), 400
            
        try:
            tone = int(tone)
        except ValueError:
            return jsonify({
                "status": "error",
                "message": "声调必须是数字"
            }), 400
            
        # 保存上传的音频文件
        with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_file:
            temp_path = temp_file.name
            audio_file.save(temp_path)
        
        # 使用Parselmouth分析音频
        try:
            sound = parselmouth.Sound(temp_path)
            pitch = sound.to_pitch(pitch_floor=75.0, pitch_ceiling=500.0)
            
            # 获取基频和时间信息
            pitch_values = pitch.selected_array['frequency'].tolist()
            timestamps = pitch.xs().tolist()
            
            # 过滤掉未检测到的基频点（值为0）
            filtered_data = [
                {"time": time, "frequency": freq} 
                for time, freq in zip(timestamps, pitch_values) 
                if freq > 0
            ]
            
            # 清理临时文件
            os.unlink(temp_path)
            
            if not filtered_data:
                return jsonify({
                    "status": "error",
                    "message": "未检测到有效的基频数据"
                }), 400
                
            # 构建数据格式用于分析
            user_audio_data = {
                "status": "success",
                "data": filtered_data
            }
            
            # 分析用户音频数据
            user_analysis = analyze_audio_data(user_audio_data)
            
            if "error" in user_analysis:
                return jsonify({
                    "status": "error",
                    "message": user_analysis["error"]
                }), 400
            
            # 查询标准音频数据
            query = """
            SELECT frequency_data
            FROM standard_audios
            WHERE character_text = %s AND pinyin = %s AND tone_type = %s
            LIMIT 1
            """
            
            standard_result = execute_query(query, (character, pinyin, tone))
            
            if not standard_result:
                return jsonify({
                    "status": "error",
                    "message": f"未找到字'{character}'(拼音:{pinyin}, 声调:{tone})的标准音频数据"
                }), 404
                
            # 解析标准频率数据
            try:
                standard_freq_data = json.loads(standard_result[0]["frequency_data"])
            except (json.JSONDecodeError, TypeError):
                return jsonify({
                    "status": "error",
                    "message": "标准音频数据格式错误"
                }), 500
                
            # 构建标准音频数据格式
            standard_audio_data = {
                "status": "success",
                "data": standard_freq_data
            }
            
            # 分析标准音频数据
            standard_analysis = analyze_audio_data(standard_audio_data)
            
            if "error" in standard_analysis:
                return jsonify({
                    "status": "error",
                    "message": f"标准音频分析失败: {standard_analysis['error']}"
                }), 500
            
            # 构建返回结果
            result = {
                "status": "success",
                "user_audio": {
                    "normalized_points": user_analysis["normalized_points"],
                    "fit_params": user_analysis["fit_params"],
                    "fit_curve_points": user_analysis["fit_curve_points"],
                    "tone_type": user_analysis["tone_type"]
                },
                "standard_audio": {
                    "normalized_points": standard_analysis["normalized_points"],
                    "fit_params": standard_analysis["fit_params"],
                    "fit_curve_points": standard_analysis["fit_curve_points"],
                    "tone_type": standard_analysis["tone_type"]
                },
                "character": character,
                "pinyin": pinyin,
                "tone": tone
            }
            
            return jsonify(result)
            
        except Exception as e:
            # 确保临时文件被删除
            if os.path.exists(temp_path):
                os.unlink(temp_path)
            raise e
    
    except Exception as e:
        return jsonify({
            "status": "error",
            "message": str(e)
        }), 500

def get_character_audio(character, pinyin):
    """
    接口4：查询单字音频，接受字和拼音返回标准音频
    
    参数:
        character (str): 汉字
        pinyin (str): 拼音
        
    返回:
        标准音频文件或错误信息
    """
    try:
        query = """
        SELECT audio_path
        FROM standard_audios
        WHERE character_text = %s AND pinyin = %s
        LIMIT 1
        """
        
        result = execute_query(query, (character, pinyin))
        
        if not result:
            return jsonify({
                "status": "error",
                "message": f"未找到字'{character}'(拼音:{pinyin})的标准音频"
            }), 404
            
        audio_path = result[0]["audio_path"]
        
        if not os.path.exists(audio_path):
            return jsonify({
                "status": "error",
                "message": f"标准音频文件不存在: {audio_path}"
            }), 404
            
        return send_file(audio_path, mimetype="audio/wav", as_attachment=True, 
                         download_name=f"{character}_{pinyin}.wav")
    
    except Exception as e:
        return jsonify({
            "status": "error",
            "message": str(e)
        }), 500 